命令注入(Command Injection) 是一種攻擊者利用應用程式的漏洞,將未經驗證的惡意輸入作為系統命令來執行的網路攻擊類型。這類攻擊會使應用程式直接將輸入內容作為底層操作系統指令來執行,如果這些指令沒有經過適當的驗證與過濾,攻擊者便能藉此操控系統,執行任意命令,甚至完全控制伺服器。
常見的命令注入漏洞發生在程式設計不佳的應用中,當使用者輸入的內容直接嵌入到系統指令中執行時,攻擊者可插入額外的命令。例如,當應用程式中某個輸入欄位允許使用者提交查詢字串,而這些字串未經過濾,攻擊者可嘗試構建類似的惡意請求來操控系統:
正常情況下:
https://example.com/search?query=test
後端執行的查詢字串:
grep test data.txt
如果輸入未經過濾,攻擊者可藉此插入系統命令,例如:
https://example.com/search?query=test; ls
後端執行 ls 指令,列出伺服器中的檔案:
grep apple data.txt; ls
Linux/Unix 系統:
ls
:列出目錄檔案whoami
:查看當前使用者cat
:讀取檔案內容rm
:刪除檔案或目錄ifconfig
:查詢網路配置uname -a
:顯示系統資訊Windows 系統:
dir
:列出目錄檔案whoami
:查看當前使用者type
:顯示檔案內容del
:刪除檔案ipconfig
:查詢網路配置tasklist
:顯示執行中的程序列表在構建命令注入攻擊時,攻擊者常利用多種連接符來串接多個指令。例如:
;
:終止第一個命令並執行第二個命令。例如:command1; command2
&&
:只有當第一個命令成功時,才會執行第二個命令。例如:command1 && command2
||
:當第一個命令失敗時,執行第二個命令。例如:command1 || command2
輸入驗證與過濾:
來自使用者的所有輸入應該經過嚴格的驗證和過濾,特別是特殊符號(如 ;
、&
、|
等)應進行過濾。可以使用白名單方式,僅允許合法字符。
使用安全 API:
避免直接將使用者輸入嵌入到系統指令中,例如在 PHP 中避免使用 exec()、system()。使用更安全的系統函數或 API 替代。
最小權限原則:
確保應用程式只擁有最低限度的系統權限,即使攻擊者成功注入命令,損害也能降到最低。
避免暴露錯誤訊息:
應用程式在處理指令時,應避免將具體的錯誤訊息返回給使用者,防止攻擊者根據錯誤提示進行進一步的惡意操作。
那進入今天的題目練習環節
LAB_1 - caas
似乎可以藉由在 URL 上面打上想要的字,讓牛說出我們想讓牠說的話
來看看題目附上的index.js
,發現
const express = require('express');
const app = express();
const { exec } = require('child_process');
app.use(express.static('public'));
app.get('/cowsay/:message', (req, res) => {
exec(`/usr/games/cowsay ${req.params.message}`, {timeout: 5000}, (error, stdout) => {
if (error) return res.status(500).end();
res.type('txt').send(stdout).end();
});
});
app.listen(3000, () => {
console.log('listening');
});
在第 8 行發現是使用 exec()
來執行 URL 後面的輸入,那我們先試一下基本的ls
,用;
閉合前面的區間。;ls
後看到一個 falg.txt 的檔案
接下來想辦法印出 falg.txt 的內容,一樣指令間都使用;
分隔。;ls;cat falg.txt
成功拿到 flag 啦~
今天的練習就到這邊,以下是參考資料,請搭配服用:
Injection Attack
Command Injection (一)
Command Injection (二)
命令執行漏洞
內文如有錯誤,還請不吝指教~